﻿// 使用Excel 2003 仅测试文件是否重算
#if ENABLE_EXCEL_COM
#define ENABLE_AutoItX
namespace suite_recalc
{
    using System;
    using System.Xml;
    using System.Collections.Generic;
    public class CRecalc : suit_base.SuiteBase
    {
        internal CStatistical m_statistical = new CStatistical();
        private string m_sSamplePath;
        private string m_sExcelPath;
        private autoIt.CAutoIt m_wndKill;
        private Dictionary<string, List<tool.CAddInfoHlp.CFileInfo>> m_fileDic;

        public override string GetCommand()
        {
            return ET_Improve.Global.CMD_RECALC;
        }

        public override void Call()
        {
            try
            {
                LoadConfig();
                excelOp.ExcelOP.RegisterExcel(m_sExcelPath);
                m_fileDic = tool.CAddInfoHlp.GetFolderFiles(m_sSamplePath, ET_Improve.Global.CMD_RECALC);

                m_wndKill = new autoIt.CAutoIt();
                m_wndKill.Start();
                foreach (string sDir in m_fileDic.Keys)
                {
                    if (CStatistical.IsAnalysed(sDir) || m_fileDic[sDir].Count == 0)
                    {
                        continue;
                    }

                    tool.LogTool.GetInstance().BeginUseLog(sDir, ET_Improve.Global.s_curCmdName);

                    m_statistical.StartDir();
                    foreach (tool.CAddInfoHlp.CFileInfo fi in m_fileDic[sDir])
                    {
                        tool.Output.DumpWriteLine("> IsFileRecalc:" + fi.FileName);
                        IsFileRecalc(fi);
                    }
                    m_statistical.SaveExpFile(sDir);

                    tool.LogTool.GetInstance().EndUseLog();
                }
                tool.Output.DumpWriteLine(">>>>>>recalc completed!<<<<<<");
            }
            catch (tool.ETImpException ex)
            {
                ex.AddLog();
            }
            catch (System.Exception ex)
            {
                tool.Output.DumpWriteLine(ex.ToString());
            }
            finally
            {
                m_statistical.SaveExpFile(null);
                m_wndKill.Stop();
            }
        }

        protected void LoadConfig()
        {
            const string LOG_ROOT = "RecalcFile";
            const string LOG_SAMPLE = "SamplePath";
            const string LOG_EXCEL = "ExcelPath";
            try
            {
                XmlDocument doc = new XmlDocument();
                XmlNodeList xnl = tool.ConfigReader.GetElementList(LOG_ROOT);
                foreach (XmlNode ele in xnl)
                {
                    if (ele.Name == LOG_SAMPLE)
                    {
                        m_sSamplePath = ele.InnerText;
                    }
                    else if(ele.Name == LOG_EXCEL)
                    {
                        m_sExcelPath = ele.InnerText;
                    }
                }
            }
            catch (System.Exception ex)
            {
                tool.Output.DumpWriteLine(ex.ToString());
                throw ex;
            }
        }

        public void IsFileRecalc(tool.CAddInfoHlp.CFileInfo fi)
        {
            m_statistical.AddItem(SumItem.TOTAL);
            excelOp.ExcelOP pExcel = new excelOp.ExcelOP();
            try
            {
                m_wndKill.BeginMonitor(false);
                pExcel.Init(m_wndKill, true);
                pExcel.Open(fi.FileName, fi.Password);

                if (pExcel.IsRecalculate())
                {
                    m_statistical.AddItem(SumItem.RECALC);
                    tool.Output.DumpWriteLine(">Recalc<");
                }
                else
                {
                    tool.Output.DumpWriteLine(">Normal<");
                }
                pExcel.Close();
            }
            catch (tool.ETImpException ex)
            {
                if(ex.LogType == tool.LogTool.LOG_TYPE.NO_PASSWORD)
                {
                    m_statistical.AddItem(SumItem.NO_PASSWORD);
                    tool.Output.DumpWriteLine(">Need password<");
                }
                else
                {
                    m_statistical.AddItem(SumItem.FAILED);
                    tool.Output.DumpWriteLine(">Failed<");
                }
                ex.AddLog();
            }
            catch (System.Exception ex)
            {
                tool.LogTool.GetInstance().AddLog(tool.LogTool.LOG_TYPE.EXCEPTION, fi.FileName, null, ex);
                m_statistical.AddItem(SumItem.FAILED);
            }
            finally
            {
                m_wndKill.EndMonitor();
                excelOp.ExcelOP.DestoryExcelOp(ref pExcel);
            }
        }
    }

    // 统计对象
    internal class CStatistical
    {
        private const string EXP_FILENAME = "exp_recalc.xml";
        private const string NODE_NAME = "RecalcSummary";
        private Dictionary<SumItem, long> m_dirSummary;     // 当前目录的统计数目
        private Dictionary<SumItem, long> m_totalSummary;   // 样张目录总共统计数目
        public CStatistical()
        {
            m_dirSummary = new Dictionary<SumItem, long>();
            m_totalSummary = new Dictionary<SumItem, long>();
            InitSummary(m_dirSummary);
            InitSummary(m_totalSummary);
        }

        public static bool IsAnalysed(string sDir)
        {
            tool.CAddInfoHlp.ValidDirectory(ref sDir);
            string sPathName = sDir + EXP_FILENAME;
            return System.IO.File.Exists(sPathName);
        }

        internal void InitSummary(Dictionary<SumItem, long> dic)
        {
            dic.Add(SumItem.TOTAL, 0);
            dic.Add(SumItem.RECALC, 0);
            dic.Add(SumItem.NO_PASSWORD, 0);
            dic.Add(SumItem.FAILED, 0);
        }

        public void StartDir()
        {
            Type sumItems = typeof(SumItem);
            foreach (string s in Enum.GetNames(sumItems))
            {
                m_dirSummary[(SumItem)Enum.Parse(sumItems, s)] = 0;
            }
        }

        public void AddItem(SumItem item)
        {
            ++m_dirSummary[item];
            ++m_totalSummary[item];
        }

        // 如果是全局数据 sCurDir = null
        public void SaveExpFile(string sCurDir)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                XmlDeclaration xmlDec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
                doc.InsertBefore(xmlDec, doc.DocumentElement);
                XmlElement rootNode = doc.CreateElement("", "root", "");
                doc.AppendChild(rootNode);

                XmlComment comment = doc.CreateComment(tool.CTimer.GetTimeComment());
                rootNode.AppendChild(comment);

                string sDstFile;
                if(sCurDir != null)
                {
                    
                    AddResult(m_dirSummary, doc, rootNode);
                }
                else
                {
                    sCurDir = ET_Improve.Global.m_strDefaultDir;
                    AddResult(m_totalSummary, doc, rootNode);
                }

                tool.CAddInfoHlp.ValidDirectory(ref sCurDir);
                sDstFile = sCurDir + EXP_FILENAME;
                doc.Save(sDstFile);
            }
            catch (System.Exception ex)
            {
                tool.Output.DumpWriteLine(ex.ToString());
                tool.LogTool.GetInstance().AddLog(tool.LogTool.LOG_TYPE.ERROR, null, "CreateExpFile失败", ex);
            }
        }

        protected void AddResult(Dictionary<SumItem, long> dic, XmlDocument doc, XmlElement root)
        {
            XmlElement node = doc.CreateElement("", NODE_NAME, "");
            node.SetAttribute(SumItem.TOTAL.ToString(), dic[SumItem.TOTAL].ToString());
            node.SetAttribute(SumItem.RECALC.ToString(), dic[SumItem.RECALC].ToString());
            node.SetAttribute(SumItem.NO_PASSWORD.ToString(), dic[SumItem.NO_PASSWORD].ToString());
            node.SetAttribute(SumItem.FAILED.ToString(), dic[SumItem.FAILED].ToString());
            root.AppendChild(node);
        }
    }

    internal enum SumItem
    {
        TOTAL = 0,
        RECALC,
        NO_PASSWORD,
        FAILED,
    }
}
#endif // #if ENABLE_EXCEL_COM